<!DOCTYPE html>
<html>
<head>
<title>Electromagnetic Field Diagram</title>
</head>
<body>
<canvas id="physicsCanvas" width="500" height="550"></canvas>
<script>
const canvas = document.getElementById('physicsCanvas');
const ctx = canvas.getContext('2d');

// --- Helper Function ---
/**
 * Draws a line from (fromx, fromy) to (tox, toy) with an arrowhead at the end.
 * @param {CanvasRenderingContext2D} ctx - The canvas rendering context.
 * @param {number} fromx - The x-coordinate of the starting point.
 * @param {number} fromy - The y-coordinate of the starting point.
 * @param {number} tox - The x-coordinate of the ending point.
 * @param {number} toy - The y-coordinate of the ending point.
 * @param {number} arrowSize - The size of the arrowhead.
 */
function drawArrowedLine(ctx, fromx, fromy, tox, toy, arrowSize = 10) {
    const angle = Math.atan2(toy - fromy, tox - fromx);
    
    // Draw the line segment
    ctx.beginPath();
    ctx.moveTo(fromx, fromy);
    ctx.lineTo(tox, toy);
    ctx.stroke();

    // Draw the arrowhead
    ctx.beginPath();
    ctx.moveTo(tox, toy);
    ctx.lineTo(tox - arrowSize * Math.cos(angle - Math.PI / 6), toy - arrowSize * Math.sin(angle - Math.PI / 6));
    ctx.moveTo(tox, toy);
    ctx.lineTo(tox - arrowSize * Math.cos(angle + Math.PI / 6), toy - arrowSize * Math.sin(angle + Math.PI / 6));
    ctx.stroke();
}

// --- Main Drawing ---

// Style settings
ctx.strokeStyle = 'black';
ctx.fillStyle = 'black';
ctx.lineWidth = 2;

// Define coordinates and dimensions, using a scale to maintain proportions (d:b:l = 1:9:20)
const scale = 10;
const d = 1.0 * scale; // 10px
const b = 9.0 * scale; // 90px
const l = 20.0 * scale; // 200px

const wireX = 120;
const loopTopY = 100;

const loopLeftX = wireX + d;
const loopRightX = loopLeftX + b;
const loopBottomY = loopTopY + l;

// 1. Draw the long straight wire (I₁)
ctx.save();
// Dashed part top
ctx.setLineDash([6, 6]);
ctx.beginPath();
ctx.moveTo(wireX, loopTopY - 80);
ctx.lineTo(wireX, loopTopY - 20);
ctx.stroke();

// Solid part
ctx.setLineDash([]);
ctx.beginPath();
ctx.moveTo(wireX, loopTopY - 20);
ctx.lineTo(wireX, loopBottomY + 20);
ctx.stroke();

// Dashed part bottom
ctx.setLineDash([6, 6]);
ctx.beginPath();
ctx.moveTo(wireX, loopBottomY + 20);
ctx.lineTo(wireX, loopBottomY + 80);
ctx.stroke();

// Arrow for I₁
const i1_arrow_y = loopTopY + l / 3;
drawArrowedLine(ctx, wireX, i1_arrow_y + 20, wireX, i1_arrow_y, 10);

// Label for I₁
ctx.font = 'italic 22px Times New Roman';
ctx.textAlign = 'right';
ctx.textBaseline = 'middle';
const i1_label_x = wireX - 20;
const i1_label_y = loopTopY + l / 4;
ctx.fillText('I', i1_label_x, i1_label_y);
ctx.font = 'italic 16px Times New Roman';
ctx.fillText('1', i1_label_x + 5, i1_label_y + 8);
ctx.restore();

// 2. Draw the rectangular loop (I₂)
ctx.beginPath();
ctx.rect(loopLeftX, loopTopY, b, l);
ctx.stroke();

// Arrows for I₂ current
const arrowOffset = 20;
// Top arrow (->)
drawArrowedLine(ctx, loopLeftX + b / 2 - arrowOffset, loopTopY, loopLeftX + b / 2 + arrowOffset, loopTopY, 10);
// Right arrow (v)
drawArrowedLine(ctx, loopRightX, loopTopY + l / 2 - arrowOffset, loopRightX, loopTopY + l / 2 + arrowOffset, 10);
// Bottom arrow (<-)
drawArrowedLine(ctx, loopLeftX + b / 2 + arrowOffset, loopBottomY, loopLeftX + b / 2 - arrowOffset, loopBottomY, 10);
// Left arrow (^)
drawArrowedLine(ctx, loopLeftX, loopTopY + l / 2 + arrowOffset, loopLeftX, loopTopY + l / 2 - arrowOffset, 10);

// Label for I₂
ctx.save();
ctx.font = 'italic 22px Times New Roman';
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
const i2_label_x = loopLeftX + b / 2;
const i2_label_y = loopTopY - 10;
ctx.fillText('I', i2_label_x, i2_label_y);
ctx.font = 'italic 16px Times New Roman';
ctx.fillText('2', i2_label_x + 8, i2_label_y + 5);
ctx.restore();


// 3. Draw Dimension Lines
ctx.save();
ctx.lineWidth = 1;
ctx.font = 'italic 20px Times New Roman';

// --- Dimension for 'd' and 'b' ---
const dim_y_bottom = loopBottomY + 40;
// Extension lines
ctx.beginPath();
ctx.moveTo(wireX, loopBottomY);
ctx.lineTo(wireX, dim_y_bottom);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(loopLeftX, loopBottomY);
ctx.lineTo(loopLeftX, dim_y_bottom);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(loopRightX, loopBottomY);
ctx.lineTo(loopRightX, dim_y_bottom);
ctx.stroke();

// 'd' dimension line
drawArrowedLine(ctx, loopLeftX, dim_y_bottom, wireX, dim_y_bottom, 8);
drawArrowedLine(ctx, wireX, dim_y_bottom, loopLeftX, dim_y_bottom, 8);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
ctx.fillText('d', wireX + d / 2, dim_y_bottom - 5);

// 'b' dimension line
drawArrowedLine(ctx, loopRightX, dim_y_bottom, loopLeftX, dim_y_bottom, 8);
drawArrowedLine(ctx, loopLeftX, dim_y_bottom, loopRightX, dim_y_bottom, 8);
ctx.fillText('b', loopLeftX + b / 2, dim_y_bottom - 5);


// --- Dimension for 'l' ---
const dim_x_right = loopRightX + 40;
// Extension lines
ctx.beginPath();
ctx.moveTo(loopRightX, loopTopY);
ctx.lineTo(dim_x_right, loopTopY);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(loopRightX, loopBottomY);
ctx.lineTo(dim_x_right, loopBottomY);
ctx.stroke();

// 'l' dimension line
drawArrowedLine(ctx, dim_x_right, loopBottomY, dim_x_right, loopTopY, 8);
drawArrowedLine(ctx, dim_x_right, loopTopY, dim_x_right, loopBottomY, 8);
ctx.textAlign = 'left';
ctx.textBaseline = 'middle';
ctx.fillText('l', dim_x_right + 10, loopTopY + l / 2);

ctx.restore();

// 4. Draw the bottom text label
ctx.font = '24px KaiTi'; // Use a font that supports Chinese characters
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
ctx.fillText('习题 8-42 图', canvas.width / 2, canvas.height - 20);

</script>
</body>
</html>